// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.inventory.types;

import java.io.IOException;
import java.nio.ByteBuffer;
import zombie.ai.sadisticAIDirector.SleepingEvent;
import zombie.audio.BaseSoundEmitter;
import zombie.characters.IsoPlayer;
import zombie.core.Rand;
import zombie.core.Translator;
import zombie.core.network.ByteBufferWriter;
import zombie.core.utils.OnceEvery;
import zombie.inventory.InventoryItem;
import zombie.inventory.ItemContainer;
import zombie.inventory.ItemSoundManager;
import zombie.inventory.ItemType;
import zombie.iso.IsoCell;
import zombie.iso.IsoGridSquare;
import zombie.iso.IsoObject;
import zombie.iso.IsoUtils;
import zombie.iso.IsoWorld;
import zombie.iso.objects.IsoWorldInventoryObject;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.network.PacketTypes;
import zombie.scripting.objects.Item;
import zombie.ui.ObjectTooltip;

public final class AlarmClock extends InventoryItem {
    private int alarmHour = -1;
    private int alarmMinutes = -1;
    private boolean alarmSet = false;
    private long ringSound;
    private double ringSince = -1.0;
    private int forceDontRing = -1;
    private String alarmSound = "AlarmClockLoop";
    private int soundRadius = 40;
    private boolean isDigital = true;
    public static short PacketPlayer = 1;
    public static short PacketWorld = 2;
    private static final OnceEvery sendEvery = new OnceEvery(2.0F);

    public AlarmClock(String module, String name, String itemType, String texName) {
        super(module, name, itemType, texName);
        if (name.contains("Classic")) {
            this.isDigital = false;
        }

        this.cat = ItemType.AlarmClock;
        this.randomizeAlarm();
    }

    public AlarmClock(String module, String name, String itemType, Item item) {
        super(module, name, itemType, item);
        if (name.contains("Classic")) {
            this.isDigital = false;
        }

        this.cat = ItemType.AlarmClock;
        this.randomizeAlarm();
    }

    private void randomizeAlarm() {
        this.alarmHour = Rand.Next(0, 23);
        this.alarmMinutes = (int)Math.floor((double)(Rand.Next(0, 59) / 10)) * 10;
        this.alarmSet = Rand.Next(6) == 1;
    }

    public IsoGridSquare getAlarmSquare() {
        IsoGridSquare isoGridSquare = null;
        ItemContainer itemContainer = this.getOutermostContainer();
        if (itemContainer != null) {
            isoGridSquare = itemContainer.getSourceGrid();
            if (isoGridSquare == null && itemContainer.parent != null) {
                isoGridSquare = itemContainer.parent.square;
            }

            InventoryItem inventoryItem = itemContainer.containingItem;
            if (isoGridSquare == null && inventoryItem != null && inventoryItem.getWorldItem() != null) {
                isoGridSquare = inventoryItem.getWorldItem().getSquare();
            }
        }

        if (isoGridSquare == null && this.getWorldItem() != null && this.getWorldItem().getWorldObjectIndex() != -1) {
            isoGridSquare = this.getWorldItem().square;
        }

        return isoGridSquare;
    }

    @Override
    public boolean shouldUpdateInWorld() {
        return this.alarmSet;
    }

    @Override
    public void update() {
        if (this.alarmSet) {
            int _int = zombie.GameTime.instance.getMinutes() / 10 * 10;
            if (!this.isRinging() && this.forceDontRing != _int && this.alarmHour == zombie.GameTime.instance.getHour() && this.alarmMinutes == _int) {
                this.ringSince = zombie.GameTime.getInstance().getWorldAgeHours();
            }

            if (this.isRinging()) {
                double _double = zombie.GameTime.getInstance().getWorldAgeHours();
                if (this.ringSince > _double) {
                    this.ringSince = _double;
                }

                IsoGridSquare isoGridSquare = this.getAlarmSquare();
                if (isoGridSquare == null || this.ringSince + 0.5 < _double) {
                    this.stopRinging();
                } else if (!GameClient.bClient && isoGridSquare != null) {
                    zombie.WorldSoundManager.instance
                        .addSoundRepeating(null, isoGridSquare.getX(), isoGridSquare.getY(), isoGridSquare.getZ(), this.getSoundRadius(), 3, false);
                }

                if (!GameServer.bServer && this.isRinging()) {
                    ItemSoundManager.addItem(this);
                }
            }

            if (this.forceDontRing != _int) {
                this.forceDontRing = -1;
            }
        }
    }

    @Override
    public void updateSound(BaseSoundEmitter emitter) {
        assert !GameServer.bServer;

        IsoGridSquare isoGridSquare = this.getAlarmSquare();
        if (isoGridSquare != null) {
            emitter.setPos((float)isoGridSquare.x + 0.5F, (float)isoGridSquare.y + 0.5F, (float)isoGridSquare.z);
            if (!emitter.isPlaying(this.ringSound)) {
                if (this.alarmSound == null || "".equals(this.alarmSound)) {
                    this.alarmSound = "AlarmClockLoop";
                }

                this.ringSound = emitter.playSoundImpl(this.alarmSound, isoGridSquare);
            }

            if (GameClient.bClient && sendEvery.Check() && this.isInLocalPlayerInventory()) {
                GameClient.instance.sendWorldSound(null, isoGridSquare.x, isoGridSquare.y, isoGridSquare.z, this.getSoundRadius(), 3, false, 0.0F, 1.0F);
            }

            this.wakeUpPlayers(isoGridSquare);
        }
    }

    private void wakeUpPlayers(IsoGridSquare isoGridSquare0) {
        if (!GameServer.bServer) {
            int int0 = this.getSoundRadius();
            int int1 = Math.max(isoGridSquare0.getZ() - 3, 0);
            int int2 = Math.min(isoGridSquare0.getZ() + 3, 8);

            for (int int3 = 0; int3 < IsoPlayer.numPlayers; int3++) {
                IsoPlayer isoPlayer = IsoPlayer.players[int3];
                if (isoPlayer != null && !isoPlayer.isDead() && isoPlayer.getCurrentSquare() != null && !isoPlayer.Traits.Deaf.isSet()) {
                    IsoGridSquare isoGridSquare1 = isoPlayer.getCurrentSquare();
                    if (isoGridSquare1.z >= int1 && isoGridSquare1.z < int2) {
                        float _float = IsoUtils.DistanceToSquared(
                            (float)isoGridSquare0.x, (float)isoGridSquare0.y, (float)isoGridSquare1.x, (float)isoGridSquare1.y
                        );
                        if (isoPlayer.Traits.HardOfHearing.isSet()) {
                            _float *= 4.5F;
                        }

                        if (!(_float > (float)(int0 * int0))) {
                            this.wakeUp(isoPlayer);
                        }
                    }
                }
            }
        }
    }

    private void wakeUp(IsoPlayer isoPlayer) {
        if (isoPlayer.Asleep) {
            zombie.SoundManager.instance.setMusicWakeState(isoPlayer, "WakeNormal");
            SleepingEvent.instance.wakeUp(isoPlayer);
        }
    }

    public boolean isRinging() {
        return this.ringSince >= 0.0;
    }

    @Override
    public boolean finishupdate() {
        return !this.alarmSet;
    }

    public boolean isDigital() {
        return this.isDigital;
    }

    @Override
    public void DoTooltip(ObjectTooltip tooltipUI, ObjectTooltip.Layout layout) {
        ObjectTooltip.LayoutItem layoutItem = layout.addItem();
        layoutItem.setLabel(Translator.getText("IGUI_CurrentTime"), 1.0F, 1.0F, 0.8F, 1.0F);
        int _int = zombie.GameTime.instance.getMinutes() / 10 * 10;
        layoutItem.setValue(zombie.GameTime.getInstance().getHour() + ":" + (_int == 0 ? "00" : _int), 1.0F, 1.0F, 0.8F, 1.0F);
        if (this.alarmSet) {
            layoutItem = layout.addItem();
            layoutItem.setLabel(Translator.getText("IGUI_AlarmIsSetFor"), 1.0F, 1.0F, 0.8F, 1.0F);
            layoutItem.setValue(this.alarmHour + ":" + (this.alarmMinutes == 0 ? "00" : this.alarmMinutes), 1.0F, 1.0F, 0.8F, 1.0F);
        }
    }

    @Override
    public void save(ByteBuffer output, boolean net) throws IOException {
        super.save(output, net);
        output.putInt(this.alarmHour);
        output.putInt(this.alarmMinutes);
        output.put((byte)(this.alarmSet ? 1 : 0));
        output.putFloat((float)this.ringSince);
    }

    @Override
    public void load(ByteBuffer input, int WorldVersion) throws IOException {
        super.load(input, WorldVersion);
        this.alarmHour = input.getInt();
        this.alarmMinutes = input.getInt();
        this.alarmSet = input.get() == 1;
        this.ringSince = (double)input.getFloat();
        this.ringSound = -1L;
    }

    @Override
    public int getSaveType() {
        return Item.Type.AlarmClock.ordinal();
    }

    @Override
    public String getCategory() {
        return this.mainCategory != null ? this.mainCategory : "AlarmClock";
    }

    public void setAlarmSet(boolean _alarmSet) {
        this.stopRinging();
        this.alarmSet = _alarmSet;
        this.ringSound = -1L;
        if (_alarmSet) {
            IsoWorld.instance.CurrentCell.addToProcessItems(this);
            IsoWorldInventoryObject isoWorldInventoryObject = this.getWorldItem();
            if (isoWorldInventoryObject != null && isoWorldInventoryObject.getSquare() != null) {
                IsoCell isoCell = IsoWorld.instance.getCell();
                if (!isoCell.getProcessWorldItems().contains(isoWorldInventoryObject)) {
                    isoCell.getProcessWorldItems().add(isoWorldInventoryObject);
                }
            }
        } else {
            IsoWorld.instance.CurrentCell.addToProcessItemsRemove(this);
        }
    }

    public boolean isAlarmSet() {
        return this.alarmSet;
    }

    public void setHour(int hour) {
        this.alarmHour = hour;
        this.forceDontRing = -1;
    }

    public void setMinute(int min) {
        this.alarmMinutes = min;
        this.forceDontRing = -1;
    }

    public int getHour() {
        return this.alarmHour;
    }

    public int getMinute() {
        return this.alarmMinutes;
    }

    public void syncAlarmClock() {
        IsoPlayer isoPlayer = this.getOwnerPlayer(this.container);
        if (isoPlayer != null) {
            this.syncAlarmClock_Player(isoPlayer);
        }

        if (this.worldItem != null) {
            this.syncAlarmClock_World();
        }
    }

    private IsoPlayer getOwnerPlayer(ItemContainer itemContainer) {
        if (itemContainer == null) {
            return null;
        } else {
            IsoObject isoObject = itemContainer.getParent();
            return isoObject instanceof IsoPlayer ? (IsoPlayer)isoObject : null;
        }
    }

    public void syncAlarmClock_Player(IsoPlayer player) {
        if (GameClient.bClient) {
            ByteBufferWriter byteBufferWriter = GameClient.connection.startPacket();
            PacketTypes.PacketType.SyncAlarmClock.doPacket(byteBufferWriter);
            byteBufferWriter.putShort(PacketPlayer);
            byteBufferWriter.putShort((short)player.getPlayerNum());
            byteBufferWriter.putInt(this.id);
            byteBufferWriter.putByte((byte)0);
            byteBufferWriter.putInt(this.alarmHour);
            byteBufferWriter.putInt(this.alarmMinutes);
            byteBufferWriter.putByte((byte)(this.alarmSet ? 1 : 0));
            PacketTypes.PacketType.SyncAlarmClock.send(GameClient.connection);
        }
    }

    public void syncAlarmClock_World() {
        if (GameClient.bClient) {
            ByteBufferWriter byteBufferWriter = GameClient.connection.startPacket();
            PacketTypes.PacketType.SyncAlarmClock.doPacket(byteBufferWriter);
            byteBufferWriter.putShort(PacketWorld);
            byteBufferWriter.putInt(this.worldItem.square.getX());
            byteBufferWriter.putInt(this.worldItem.square.getY());
            byteBufferWriter.putInt(this.worldItem.square.getZ());
            byteBufferWriter.putInt(this.id);
            byteBufferWriter.putByte((byte)0);
            byteBufferWriter.putInt(this.alarmHour);
            byteBufferWriter.putInt(this.alarmMinutes);
            byteBufferWriter.putByte((byte)(this.alarmSet ? 1 : 0));
            PacketTypes.PacketType.SyncAlarmClock.send(GameClient.connection);
        }
    }

    public void syncStopRinging() {
        if (GameClient.bClient) {
            ByteBufferWriter byteBufferWriter = GameClient.connection.startPacket();
            PacketTypes.PacketType.SyncAlarmClock.doPacket(byteBufferWriter);
            IsoPlayer isoPlayer = this.getOwnerPlayer(this.container);
            if (isoPlayer != null) {
                byteBufferWriter.putShort(PacketPlayer);
                byteBufferWriter.putShort((short)isoPlayer.getPlayerNum());
            } else if (this.getWorldItem() != null) {
                byteBufferWriter.putShort(PacketWorld);
                byteBufferWriter.putInt(this.worldItem.square.getX());
                byteBufferWriter.putInt(this.worldItem.square.getY());
                byteBufferWriter.putInt(this.worldItem.square.getZ());
            } else {
                assert false;
            }

            byteBufferWriter.putInt(this.id);
            byteBufferWriter.putByte((byte)1);
            PacketTypes.PacketType.SyncAlarmClock.send(GameClient.connection);
        }
    }

    public void stopRinging() {
        if (this.ringSound != -1L) {
            this.ringSound = -1L;
            IsoGridSquare isoGridSquare = this.getAlarmSquare();
            if (isoGridSquare != null) {
                BaseSoundEmitter baseSoundEmitter = IsoWorld.instance
                    .getFreeEmitter((float)isoGridSquare.x + 0.5F, (float)isoGridSquare.y + 0.5F, (float)isoGridSquare.z);
                baseSoundEmitter.playSoundImpl("AlarmClockRingingStop", isoGridSquare);
            }
        }

        ItemSoundManager.removeItem(this);
        this.ringSince = -1.0;
        this.forceDontRing = zombie.GameTime.instance.getMinutes() / 10 * 10;
    }

    public String getAlarmSound() {
        return this.alarmSound;
    }

    public void setAlarmSound(String _alarmSound) {
        this.alarmSound = _alarmSound;
    }

    public int getSoundRadius() {
        return this.soundRadius;
    }

    public void setSoundRadius(int _soundRadius) {
        this.soundRadius = _soundRadius;
    }
}
